////.hpp对应的是开源软件的后缀名,函数的声明和实现可以放在一个文件里面

//实现一个简单的阻塞队列,只是实现生产者生产数据,消费者消费数据

// #include "block_queue.hpp"

// void* produce(void* arg)
// {
//     qds::block_queue<int>* bq = (qds::block_queue<int>* )arg;

//     while(true)
//     {
//         sleep(1);
//         int data = rand() % 101 ;
//         bq->push(data);
//         std::cout << "生产者产生一个数据:" << data << std::endl;
//     }
// }

// void* comsume(void* arg)
// {
//     qds::block_queue<int>* bq = (qds::block_queue<int>* )arg;

//     while(true)
//     {
//         int data = 0;
//         bq->pop(&data);
//         std::cout << "消费者消耗了一个数据:" << data << std::endl;
//     }
// }


// int main()
// {
//     srand((long long)time(nullptr));

//     qds::block_queue<int>* bq = new qds::block_queue<int>();

//     pthread_t producer, consumer;
//     pthread_create(&producer, nullptr, produce, (void* )bq);
//     pthread_create(&consumer, nullptr, comsume, (void* )bq);

//     pthread_join(producer, nullptr);
//     pthread_join(consumer, nullptr);
             
//     return 0;
// }

//实际我们使用的场景肯定不局限于,一个生产数据,一个获取数据
//生产和获取数据只是第一步,我们怎么生产这些数据,我们获取这些数据过后,怎么处理是关键
//所以这里我们实现一个可以简单生产任务和处理任务的阻塞队列
#include "block_queue.hpp"
#include "task.hpp"

void* produce(void* arg)
{
    qds::block_queue<qds::task>* bq = (qds::block_queue<qds::task>* )arg;
    std::string opers = "+-*/%"; 
    
    while(true)
    {
        sleep(1);
        //1.制造数据
        int x = rand() % 100 + 1;
        int y = rand() % 100 + 1;
        char oper = opers[rand() % 5];
        qds::task t(x, y, oper);
        //2.将数据发送到任务队列
        bq->push(t);
        std::cout << pthread_self() << ":生产者派发了一个任务:" << x << oper << y << "=?" << std::endl;

    }
}

void* comsume(void* arg)
{
    qds::block_queue<qds::task>* bq = (qds::block_queue<qds::task>* )arg;

    while(true)
    {
        qds::task t;
        //获取到了数据
        bq->pop(&t);
        //对数据进行了处理
        t();
    }
}

//我们此时实现的模型是可以满足多消费者和多生产者的
int main()
{
    srand((long long)time(nullptr));

    qds::block_queue<qds::task>* bq = new qds::block_queue<qds::task>();

    pthread_t producer1, producer2, producer3, producer4, consumer1, consumer2, consumer3, consumer4;
    pthread_create(&producer1, nullptr, produce, (void* )bq);
    pthread_create(&producer2, nullptr, produce, (void* )bq);
    pthread_create(&producer3, nullptr, produce, (void* )bq);
    pthread_create(&producer4, nullptr, produce, (void* )bq);

    pthread_create(&consumer1, nullptr, comsume, (void* )bq);
    pthread_create(&consumer2, nullptr, comsume, (void* )bq);
    pthread_create(&consumer3, nullptr, comsume, (void* )bq);
    pthread_create(&consumer4, nullptr, comsume, (void* )bq);

    pthread_join(producer1, nullptr);
    pthread_join(producer2, nullptr);
    pthread_join(producer3, nullptr);
    pthread_join(producer4, nullptr);

    pthread_join(consumer1, nullptr);
    pthread_join(consumer2, nullptr);
    pthread_join(consumer3, nullptr);
    pthread_join(consumer4, nullptr);
             
    return 0;
}
